package com.yz.sharkim.util;

import com.google.gson.*;
import com.yz.sharkim.entity.enums.CommonResult;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;

import java.io.UnsupportedEncodingException;
import java.lang.reflect.Parameter;
import java.net.URLDecoder;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;

/**
 * 类型转换器
 */
@Slf4j
public abstract class ConvertUtil {

    private static final Gson GSON;

    public static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8;

    private static final DateTimeFormatter DATE_TIME_FORMATTER =  DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    private static final DateTimeFormatter DATE_FORMATTER =  DateTimeFormatter.ofPattern("yyyy-MM-dd");

    private static final DateTimeFormatter TIME_FORMATTER =  DateTimeFormatter.ofPattern("HH:mm:ss");

    static {
        GSON = new GsonBuilder()
                .registerTypeAdapter(LocalDate.class, (JsonSerializer<LocalDate>) (src, typeOfSrc, context) ->
                        new JsonPrimitive(src.format(DATE_FORMATTER)))
                .registerTypeAdapter(LocalTime.class, (JsonSerializer<LocalTime>) (src, typeOfSrc, context) ->
                        new JsonPrimitive(src.format(TIME_FORMATTER)))
                .registerTypeAdapter(LocalDateTime.class, (JsonSerializer<LocalDateTime>) (src, typeOfSrc, context) ->
                        new JsonPrimitive(src.format(DATE_TIME_FORMATTER)))
                .registerTypeAdapter(CommonResult.class, (JsonSerializer<CommonResult>) (src, typeOfSrc, context) -> {
                    switch (src) {
                        case SUCCESS:
                            return new JsonPrimitive(1);
                        case FAILED:
                            return new JsonPrimitive(2);
                        case NO_SUPPORT:
                            return new JsonPrimitive(3);
                        default:
                            return new JsonPrimitive(0);
                    }
                })
                .registerTypeAdapter(LocalDate.class, (JsonDeserializer<LocalDate>) (json, typeOfT, context) ->
                        LocalDate.parse(json.getAsJsonPrimitive().getAsString(), DATE_FORMATTER))
                .registerTypeAdapter(LocalTime.class, (JsonDeserializer<LocalTime>) (json, typeOfT, context) ->
                        LocalTime.parse(json.getAsJsonPrimitive().getAsString(), TIME_FORMATTER))
                .registerTypeAdapter(LocalDateTime.class, (JsonDeserializer<LocalDateTime>) (json, typeOfT, context) ->
                        LocalDateTime.parse(json.getAsJsonPrimitive().getAsString(), DATE_TIME_FORMATTER))
                .serializeNulls()
                .create();
    }

    public static Object fromJson(JsonObject object, Parameter parameter) {
        try {
            return GSON.fromJson(URLDecoder.decode(object.toString(), "UTF-8"), parameter.getType());
        } catch (UnsupportedEncodingException e) {
            log.error("解码失败: {}, type: {}", object.toString(), parameter);
        }
        return null;
    }

    public static <T> T fromJson(JsonObject object, Class<T> clz) {
        return GSON.fromJson(object, clz);
    }

    public static <T> T fromJson(String string, Class<T> clz) {
        return GSON.fromJson(string, clz);
    }

    public static String toJson(Object object) {
        return GSON.toJson(object);
    }

    public static ByteBuf toByteBuf(Object object) {
        return Unpooled.copiedBuffer(GSON.toJson(object), DEFAULT_CHARSET);
    }

    public static JsonObject toJsonObject(Object object) {
        return (JsonObject) GSON.toJsonTree(object);
    }

    public static String format(String text, Object ...content) {
        if (StringUtils.isEmpty(text) || content.length == 0) {
            return text;
        }
        int i = 0;
        while (text.contains("{}")) {
            text = text.replace("{}", content[++i].toString());
        }
        return text;
    }
}
